package edu.bu.cs673.superkids123.children.model.resources;

import java.awt.Image;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;

/**
 * Class ChildrenResourceProvider
 *
 * This class provides the images and audio resources
 * required by the superkids123 application.
 * 
 * @author David Bardwell
 * @author Adam Phung
 */
public class ChildrenResourceProvider implements ChildrenResource {
	
	private static ChildrenResourceProvider instance;
	
	private ResourceType imageResourceType = ResourceType.Default;
	private ResourceType audioResourceType = ResourceType.Default;
//	private ResourceType stringResourceType = ResourceType.Default;
	
	Map<String, ImageIcon> imageMap = new HashMap<String, ImageIcon>();
	Map<String, byte[]> audioMap = new HashMap<String, byte[]>();
	
	private ChildrenResourceProvider() {
		
	}
	
	public static ChildrenResourceProvider getInstance() {
		
		if (instance == null)
			instance = new ChildrenResourceProvider();
		
		return instance;
	}
	
	@Override
	public ImageIcon getImage(String imageId) {
		
		if (!imageMap.containsKey(imageId)) { 
			XmlResourceProvider resource = new XmlResourceProvider();
			String resourceId = resource.getResource(imageId, imageResourceType);
		
		    ImageFactory imageFactory = new ImageFactory();
		    ImageIcon imageIcon = imageFactory.createImage(resourceId);
		    imageMap.put(imageId, imageIcon);
		}
		return imageMap.get(imageId);
	}
	
	@Override
	public ImageIcon getScaledImage(String imageId, float scale) {
		
		if (!imageMap.containsKey(imageId)) {
			XmlResourceProvider resource = new XmlResourceProvider();
			String resourceId = resource.getResource(imageId, imageResourceType);
		
		    ImageFactory imageFactory = new ImageFactory();
		    ImageIcon imageIcon = imageFactory.createImage(resourceId);
		    imageMap.put(imageId, imageIcon);
		}
		Image image = imageMap.get(imageId).getImage();
		return new ImageIcon(image.getScaledInstance(
				(int)Math.round(image.getWidth(null) * scale),
				(int)Math.round(image.getHeight(null) * scale),
				java.awt.Image.SCALE_SMOOTH));
	}
	
	@Override
	public ImageIcon getScaledImageByNumber(int imageNumber, float scale) {
		String imageId = NUMBER_IMAGE_MAP.get(imageNumber);
		return getScaledImage(imageId, scale);
	}
	
	@Override
	public ImageIcon getScaledImageBySymbol(String imageSymbol, float scale) {
		String imageID = SYMBOL_IMAGE_MAP.get(imageSymbol);
		return getScaledImage(imageID, scale);
	}
	
	@Override
	public byte[] getAudioContent(String audioId) {
		
		if (!audioMap.containsKey(audioId)) {
			XmlResourceProvider resource = new XmlResourceProvider();
			String resourceId = resource.getResource(audioId, audioResourceType);
		
			AudioContentFactory audioContentFactory = new AudioContentFactory();
			byte[] audioContent = audioContentFactory.createAudioContent(resourceId);
			audioMap.put(audioId, audioContent);
		}
		return audioMap.get(audioId);
	}
	
	@Override
	public byte[] getAudioContentByNumber(int audioNumber) {
		String audioId = NUMBER_AUDIO_MAP.get(audioNumber);
		return getAudioContent(audioId);
	}
	
	@Override
	public byte[] getAudioContentBySymbol(String audioSymbol) {
		String audioId = SYMBOL_AUDIO_MAP.get(audioSymbol);
		return getAudioContent(audioId);
	}
	
	/**
	 * Returns what format of resources are available 
	 * in a passed ResourceType
	 * 
	 * @param type
	 */
	public ResourceFormat getResourceFormat(ResourceType type) {
		XmlResourceProvider resource = new XmlResourceProvider();
		return resource.getResourceFormat(type);
	}

	public void setImagePolicy(ResourceType type) {
		imageResourceType = type;
		imageMap.clear();
	}
	
	public void resetImagePolicy() {
		imageResourceType = ResourceType.Default;
		imageMap.clear();
	}
	
	public void setAudioPolicy(ResourceType type) {
		audioResourceType = type;
		audioMap.clear();
	}
	
	public void resetAudioPolicy() {
		audioResourceType = ResourceType.Default;
		audioMap.clear();
	}

	@Override
	public boolean loadAllResources() {
        // load images into memory for quick run-time access
		getImage(ChildrenResource.imageNumber1);
		getImage(ChildrenResource.imageNumber2);
		getImage(ChildrenResource.imageNumber3);
		getImage(ChildrenResource.imageNumber4);
		getImage(ChildrenResource.imageNumber5);
		getImage(ChildrenResource.imageNumber6);
		getImage(ChildrenResource.imageNumber7);
		getImage(ChildrenResource.imageNumber8);
		getImage(ChildrenResource.imageNumber9);
		getImage(ChildrenResource.imageNumber10);
		getImage(ChildrenResource.imageNumber11);
		getImage(ChildrenResource.imageNumber12);

		getImage(ChildrenResource.imageBoy);
		getImage(ChildrenResource.imageGirlCat);
		getImage(ChildrenResource.imageGirlHorn);
		getImage(ChildrenResource.imageGirlPink);
		getImage(ChildrenResource.imageGirlPrincess);
		getImage(ChildrenResource.imageStar);

		getImage(ChildrenResource.imageIconBack);
		getImage(ChildrenResource.imageIconSettings);
		getImage(ChildrenResource.imageIconFolderOpen);
		
		getImage(ChildrenResource.imageCrosshair);
		getImage(ChildrenResource.imageField);
		getImage(ChildrenResource.imageTarget);


		// load audio files into memory for quick run-time access
		getAudioContent(ChildrenResource.audioNumber0);
		getAudioContent(ChildrenResource.audioNumber1);
		getAudioContent(ChildrenResource.audioNumber2);
		getAudioContent(ChildrenResource.audioNumber3);
		getAudioContent(ChildrenResource.audioNumber4);
		getAudioContent(ChildrenResource.audioNumber5);
		getAudioContent(ChildrenResource.audioNumber6);
		getAudioContent(ChildrenResource.audioNumber7);
		getAudioContent(ChildrenResource.audioNumber8);
		getAudioContent(ChildrenResource.audioNumber9);
		getAudioContent(ChildrenResource.audioNumber10);
		getAudioContent(ChildrenResource.audioNumber11);
		getAudioContent(ChildrenResource.audioNumber12);
		getAudioContent(ChildrenResource.audioNumber13);
		getAudioContent(ChildrenResource.audioNumber14);
		getAudioContent(ChildrenResource.audioNumber15);
		getAudioContent(ChildrenResource.audioNumber16);
		getAudioContent(ChildrenResource.audioNumber17);
		getAudioContent(ChildrenResource.audioNumber18);
		getAudioContent(ChildrenResource.audioNumber19);
		getAudioContent(ChildrenResource.audioNumber20);
		getAudioContent(ChildrenResource.audioPlus);
		getAudioContent(ChildrenResource.audioEquals);
		getAudioContent(ChildrenResource.audioCorrect);
		getAudioContent(ChildrenResource.audioTryAgain);
		
		return true;
	}
	
	public int getImageMapEntryCount() {
		return imageMap.values().size();
	}
	
	public int getAudioMapEntryCount() {
		return audioMap.values().size();
	}
	
	
	// quickly check implementation
	public static void main(String args[]) {
		ChildrenResourceProvider provider = new ChildrenResourceProvider();
		provider.testImages();
		provider.testAudio();
		provider.testLoadAllResources();
	}
	
	private void testImages() {
		ImageIcon number1 = getImage(ChildrenResource.imageNumber1);
		System.out.println("ImageIcon class " + number1.toString());
		
	}
	
	private void testAudio() {
		byte[] audioContent1 = getAudioContent(ChildrenResource.audioNumber1);
		System.out.println("byte[] size is " + audioContent1.length);
	}
	
	private void testLoadAllResources() {
		loadAllResources();
		System.out.println("Images contains " + imageMap.values().size());
		System.out.println("Audio contains " + audioMap.values().size());
	}


}
